package service

import (
	"context"
	"fmt"
	"github.com/sirupsen/logrus"
	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/client-go/kubernetes"
	"reflect"
	"time"
)

const (
	testNamespace = "default"       // 定义测试使用的命名空间
	testTimeout   = 1 * time.Minute // 单个测试用例的默认超时时间
	nodeName      = "agent1"        // 指定node节点名称
	appName       = "nginx"
	serviceName   = "service-test-v1"
	portsName     = "test-service-port"
)

func RunServiceTests(clientset *kubernetes.Clientset, log *logrus.Logger, selectedTestCase string) {
	log.Info("Starting Pods API tests...")

	// 运行具体的测试用例
	switch selectedTestCase {
	case "basic":
		runTestCase(clientset, log, "Basic_Service_Creation_Deletion", testServiceFieldsAndOptions)
	//case "deploy":
	//	runTestCase(clientset, log, "Deployment_Fields", testDeploymentFields)
	//case "patch":
	//	runTestCase(clientset, log, "Deployment_Patch", testDeploymentPatch)
	default:
		log.Warnf("No test case selected or invalid test case name '%s'. No tests will be executed. Available tests: basic, containers, pod.", selectedTestCase)
		// 这里不调用 runTestCase，也不做任何其他操作，直接返回
	}
	log.Info("This Service API test completed.")
}

// runTestCase 是一个通用的测试用例执行器
func runTestCase(clientset *kubernetes.Clientset, log *logrus.Logger, name string, testFunc func(*kubernetes.Clientset, *logrus.Logger) error) {
	log.Infof("--- Running Test Case: %s ---", name)
	err := testFunc(clientset, log)
	if err != nil {
		log.Errorf("Test Case %s FAILED: %v", name, err)
	} else {
		log.Infof("Test Case %s PASSED", name)
	}
}

func testServiceFieldsAndOptions(clientset *kubernetes.Clientset, log *logrus.Logger) error {
	// 这里的serviceName不能独立，要与后期的Ingress对应上

	// ServicePort数组
	testServicePorts := make([]v1.ServicePort, 1) // 必须初始化所有端口
	testServicePorts[0] = v1.ServicePort{
		Name:       portsName, // 用于多端口强制命名,命名当前81端口
		Port:       81,
		TargetPort: intstr.Parse("81"), // 对应Pod中容器暴露的端口
		Protocol:   v1.ProtocolTCP,
	}
	//
	service := &v1.Service{
		ObjectMeta: metav1.ObjectMeta{
			Name:      serviceName,
			Namespace: testNamespace,
			// 一般一个Name就差不多了
		},
		Spec: v1.ServiceSpec{
			Selector: map[string]string{"app": "hello-k3s-v2"},
			Ports:    testServicePorts,
			Type:     v1.ServiceTypeClusterIP,
		},
	}

	defer func() {
		log.Debugf("Cleaning up service %s...", serviceName)
		err := DeleteService(clientset, service, testNamespace, log)
		if err != nil {
			log.Errorf("Failed to clean up service")
		} else {
			log.Debugf("Service %s cleaned up.", serviceName)
		}
	}()

	// 创建Service
	createService, err := CreateService(clientset, service, testNamespace, log)
	if err != nil {
		return fmt.Errorf("failed to create service: %w", err)
	}
	// 验证Service中的字段
	fetchedService, err := clientset.CoreV1().Services(testNamespace).Get(context.TODO(), serviceName, metav1.GetOptions{})
	if err != nil {
		return fmt.Errorf("failed to get service %s after creation: %w", createService.Name, err)
	}
	//
	log.Infof("service namespace match %s", fetchedService.Namespace)
	if fetchedService.Name != serviceName {
		return fmt.Errorf("service name mismatch: expected 'service-test-v1', got %s", createService.Name)
	}
	log.Infof("service name match %s", fetchedService.Name)
	//
	if !reflect.DeepEqual(fetchedService.Spec.Selector, createService.Spec.Selector) {
		return fmt.Errorf("service selector mismatch: expected 'app:hello-k3s-v2', got %v", createService.Spec.Selector)
	}
	log.Infof("service selector match %v", createService.Spec.Selector)
	//
	if fetchedService.Spec.Ports[0].Name != portsName {
		return fmt.Errorf("service ports name mismatch: expected 'test-service-port', got %v", createService.Spec.Ports[0].Name)
	}
	log.Infof("service ports name match %s, prots port match %d", portsName, fetchedService.Spec.Ports[0].Port)
	// Type
	if fetchedService.Spec.Type != createService.Spec.Type {
		return fmt.Errorf("service type name mismatch: expected 'ClusterIP', got %s", fetchedService.Spec.Type)
	}
	log.Infof("service type matched %s", fetchedService.Spec.Type)
	log.Debugf("Service %s successfully created and is running.", createService.Name)
	return nil
}
